# 可以自己import我们平台支持的第三方python模块，比如pandas、numpy等。
# 为了不报错引入的模块
import logging as logger
from util.util import *
from util.finance import *
import util.scheduler as scheduler
# 机器学习使用
from sklearn.preprocessing import StandardScaler
from scipy.stats.mstats import winsorize
from sklearn.linear_model import LinearRegression, Ridge

# numpy ,panda
import pandas as pd
import numpy as np 



# 在这个方法中编写任何的初始化逻辑。context对象将会在你的算法策略的任何方法之间做传递。
def init(context):
    # 实时打印日志

    # 经常会调用指数成分股的接口
    # 获取沪深300的指数股票
    # 相当于股票池
    # 定义按月运行的一个定时运行器
    # 每月只运行一次，指定第一个交易日
    # scheduler.run_daily - 每天运行
    # scheduler.run_weekly - 每周运行,是每周第一个交易日运行
    # scheduler.run_monthly - 每月运行,是每月第一个交易日运行
    # 使传入的function每日运行。注意，function函数一定要包含（并且只能包含）context, bar_dict两个输入参数
    # tradingday为第几个交易日,
    # time_rule=market_open(hour=1) ,
    # market_open(minute=120)将在11:30执行， market_open(minute=121)在13:01执行，中午休市的区间会被忽略。
    # 在before_trading 和handler_bar中间运行函数
    # 
    scheduler.run_daily(get_data)


def get_data(context, bar_dict):
    # 市盈率 pe_ratio 
    # 市现率 pcf_ratio 
    # fundamentals获取所有股票的财务数据
    # 选股：获得市盈率大于50且小于65，营业总收入前10的股票
    q = query(fundamentals.eod_derivative_indicator.pe_ratio,
              fundamentals.income_statement.revenue
              ).filter(
        fundamentals.eod_derivative_indicator.pe_ratio > 50
    ).filter(
        fundamentals.eod_derivative_indicator.pe_ratio < 65
    ).order_by(
        fundamentals.income_statement.revenue.desc()
    ).limit(10)
    # 获取财务数据，默认获取的是dataframe，entry_date在回测当中不去要提供
    # get_fundamentals is deprecated, use get_factor instead
    fund = get_fundamentals(q)
    context.stock_list = fund.T.index


# before_trading此函数会在每天策略交易开始前被调用，当天只会被调用一次
def before_trading(context):
    pass


# 你选择的证券的数据更新将会触发此段逻辑，例如日或分钟历史数据切片或者是实时数据切片更新
# bar_dict 获取当天数据
def handle_bar(context, bar_dict):
    # 调仓：每日调仓，将所有资金平摊到这10个股票的购买策略，卖出一次性卖出所有不符合条件的
    # 先卖出不符合条件的股票,才有资金买入新的股票

    stock_list = context.portfolio.positions.keys()
    logger.info("当前持有列表 %s" % stock_list)
    logger.info("替换成列表 %s" % context.stock_list)
    if len(stock_list) != 0:
        # 卖出不在context.stock_list中的
        for stock in stock_list:
            if stock not in context.stock_list:
                order_target_percent(stock, 0)
                pass
            pass
        pass

    # 再买入调仓
    weight = 1.0 / len(context.stock_list)
    logger.info("平均持仓 %.2f" % weight)
    for stock in context.stock_list:
        # 调仓：每日调仓，将所有资金平摊到这10个股票的购买策略，卖出一次性卖出所有不符合条件的
        order_target_percent(stock, weight)
        pass

    stock_list = context.portfolio.positions.keys()
    fail_list = set(context.stock_list.tolist()) - set(stock_list)
    logger.info("未成交列表 %s" % fail_list)
    pass


# after_trading函数会在每天交易结束后被调用，当天只会被调用一次
def after_trading(context):
    pass
